<template>
  <div class="CostQuery">
    <div class="CostQuery-toolbar">
      <el-form :model="form" label-width="100px" class="CostQuery-form" inline>
        <el-form-item label="模式" prop="mode">
          <el-radio-group v-model="form.mode" @change="handleModeChange">
            <el-radio-button label="year">年</el-radio-button>
            <el-radio-button label="month">月</el-radio-button>
            <el-radio-button label="day">日</el-radio-button>
          </el-radio-group>
        </el-form-item>
        <template v-if="form.mode==='year'">
          <el-form-item label="年份范围" required>
            <div class="CostQuery-range">
              <el-select v-model="yearRange.start" placeholder="开始年" class="CostQuery-range-select" @change="validateYearRange">
                <el-option v-for="y in yearOptions" :key="y" :label="y" :value="y"/>
              </el-select>
              <span class="CostQuery-range-sep">-</span>
              <el-select v-model="yearRange.end" placeholder="结束年" class="CostQuery-range-select" @change="validateYearRange">
                <el-option v-for="y in yearOptions" :key="'e'+y" :label="y" :value="y"/>
              </el-select>
            </div>
          </el-form-item>
        </template>
        <template v-else-if="form.mode==='month'">
          <el-form-item label="月份范围" required>
            <el-date-picker v-model="monthRange" type="monthrange" range-separator="至" start-placeholder="开始月份" end-placeholder="结束月份" value-format="YYYY-MM" :disabled-date="disableFutureMonth" :clearable="false" :editable="false" @change="validateMonthRange"/>
          </el-form-item>
        </template>
        <template v-else>
          <el-form-item label="日期范围" required>
            <el-date-picker v-model="dayRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD" :disabled-date="disableFutureDay" :clearable="false" :editable="false" :shortcuts="dayShortcuts" @change="validateDayRange"/>
          </el-form-item>
        </template>
        <el-form-item label="商品" required>
          <div class="CostQuery-productSelect">
            <template v-if="selectedProduct">
              <div class="CostQuery-productSelect-info">
                <span class="CostQuery-productSelect-code">{{ selectedProduct.code }}</span>
                <span class="CostQuery-productSelect-name">{{ selectedProduct.name }}</span>
              </div>
              <el-button type="primary" link @click="openProductDialog">重选</el-button>
              <el-button type="danger" link @click="clearProduct">清除</el-button>
            </template>
            <template v-else>
              <el-button type="primary" @click="openProductDialog">选择商品</el-button>
            </template>
          </div>
        </el-form-item>
      </el-form>
      <div class="CostQuery-actions">
        <el-button type="primary" :disabled="!selectedProduct" @click="handleQuery">查询</el-button>
        <el-button @click="handleReset">重置</el-button>
      </div>
    </div>

    <div class="CostQuery-chartWrapper" v-if="chartData.length" :class="{ 'is-loading': loading }">
      <div v-if="loading" class="CostQuery-chartLoading">加载中...</div>
      <div v-else ref="chartRef" class="CostQuery-chart"></div>
    </div>
    <div v-else class="CostQuery-placeholder">请选择模式、时间范围并选择商品后点击查询，显示成本变化</div>

    <ProductSelectDialog v-model:visible="productDialogVisible" @selected="handleProductSelected"/>
  </div>
</template>

<script setup>
import {ref, reactive, watch, onMounted, onBeforeUnmount, nextTick} from 'vue'
import {ElMessage} from 'element-plus'
import * as echarts from 'echarts'
import ProductSelectDialog from '../../../components/ProductSelectDialog.vue'
import {listCostChanges} from '../../../api/costApi.js'

// 表单 / 默认
const form = reactive({mode: 'day'})
const currentYear = new Date().getFullYear()
const yearOptions = Array.from({length: 50}).map((_, i) => currentYear - i)
const yearRange = reactive({start: currentYear - 4, end: currentYear})
const monthRange = ref([])
const dayRange = ref([])

// 商品
const selectedProduct = ref(null)
const productDialogVisible = ref(false)
const openProductDialog = () => { productDialogVisible.value = true }
const handleProductSelected = (p) => { productDialogVisible.value = false; if (p) selectedProduct.value = p }
const clearProduct = () => { selectedProduct.value = null }

// 快捷
const dayShortcuts = [
  { text: '近7天', value: () => { const end = new Date(); const start = new Date(end.getTime() - (7 - 1) * 86400000); return [formatDate(start), formatDate(end)] } },
  { text: '近30天', value: () => { const end = new Date(); const start = new Date(end.getTime() - (30 - 1) * 86400000); return [formatDate(start), formatDate(end)] } }
]

// 禁用未来
const disableFutureMonth = (d) => { if (!d) return false; const now = new Date(); const diff = (d.getFullYear() - now.getFullYear()) * 12 + (d.getMonth() - now.getMonth()); return diff > 6 }
const disableFutureDay = (d) => { if (!d) return false; const now = new Date(); const max = new Date(now.getTime() + 30 * 86400000); return d.getTime() > max.getTime() }

// 工具
const formatDate = (d) => { const y = d.getFullYear(); const m = String(d.getMonth() + 1).padStart(2, '0'); const day = String(d.getDate()).padStart(2, '0'); return `${y}-${m}-${day}` }

const initMonthRange = () => { monthRange.value = [`${currentYear}-01`, `${currentYear}-12`] }
const initDayRange = () => { const end = new Date(); const start = new Date(end.getTime() - (7 - 1) * 86400000); dayRange.value = [formatDate(start), formatDate(end)] }

// 校验
const validateYearRange = () => { if (yearRange.start > yearRange.end) yearRange.end = yearRange.start; const span = yearRange.end - yearRange.start + 1; if (span > 24) { yearRange.start = yearRange.end - 23; ElMessage.warning('年份跨度不能超过 24 年') } }
const validateMonthRange = () => { if (!monthRange.value || monthRange.value.length !== 2) return; const [s, e] = monthRange.value; const [sy, sm] = s.split('-').map(Number); const [ey, em] = e.split('-').map(Number); let diff = (ey - sy) * 12 + (em - sm) + 1; if (diff > 24) { ElMessage.warning('月份跨度不能超过 24 个月'); const date = new Date(s + '-01'); date.setMonth(date.getMonth() + 23); const ny = date.getFullYear(); const nm = String(date.getMonth() + 1).padStart(2, '0'); monthRange.value = [s, `${ny}-${nm}`] } }
const validateDayRange = () => { if (!dayRange.value || dayRange.value.length !== 2) return; const [s, e] = dayRange.value; const diffDays = (new Date(e) - new Date(s)) / 86400000 + 1; if (diffDays > 60) { ElMessage.warning('日期跨度不能超过 60 天'); const end = new Date(e); const start = new Date(end.getTime() - (60 - 1) * 86400000); dayRange.value = [formatDate(start), e] } }

// 构建条件
const getLastDayOfMonth = (y, m) => new Date(y, m, 0).getDate()
const buildCondition = () => {
  if (form.mode === 'year') {
    return {
      mode: 'year',
      startDate: `${yearRange.start}-01-01`,
      endDate: `${yearRange.end}-12-31`,
      yearRange: { start: yearRange.start, end: yearRange.end }
    }
  }
  if (form.mode === 'month') {
    const [s, e] = monthRange.value || []
    if (!s || !e) return null
    const [ey, em] = e.split('-').map(Number)
    const endDay = getLastDayOfMonth(ey, em)
    return {
      mode: 'month',
      startDate: `${s}-01`,
      endDate: `${e}-${String(endDay).padStart(2, '0')}`,
      monthRange: { start: s, end: e }
    }
  }
  const [ds, de] = dayRange.value || []
  if (!ds || !de) return null
  return { mode: 'day', startDate: ds, endDate: de }
}

// 图表数据
const chartData = ref([]) // {label,cost}

const loading = ref(false)
let chartInstance = null
const chartRef = ref(null)

// 查询
const handleQuery = async () => {
  if (!selectedProduct.value) return ElMessage.error('请选择商品')
  if (form.mode === 'year') validateYearRange(); else if (form.mode === 'month') { validateMonthRange(); if (!monthRange.value || monthRange.value.length !== 2) return ElMessage.error('请选择月份范围') } else { validateDayRange(); if (!dayRange.value || dayRange.value.length !== 2) return ElMessage.error('请选择日期范围') }
  const condition = buildCondition(); if (!condition) return
  const payload = { ...condition, productId: selectedProduct.value.id }
  loading.value = true
  disposeChart(); chartData.value = []
  try {
    const res = await listCostChanges(payload)
    // 预期 res: { list:[{time,cost}] } cost 已为数值
    const list = (res && res.list) || []
    if (!Array.isArray(list) || !list.length) { ElMessage.info('该时段无成本变动'); return }
    chartData.value = list.map(item => ({ label: item.time, cost: item.cost }))
  } catch (e) {
    ElMessage.error('查询失败')
  } finally { loading.value = false }
}

// 重置
const handleReset = () => {
  form.mode = 'day'
  yearRange.start = currentYear - 4; yearRange.end = currentYear
  initMonthRange(); initDayRange(); selectedProduct.value = null
  chartData.value = []; disposeChart()
}

// 模式切换
const handleModeChange = () => {
  if (form.mode === 'year') { yearRange.start = currentYear - 4; yearRange.end = currentYear } else if (form.mode === 'month') initMonthRange(); else initDayRange()
  chartData.value = []; disposeChart()
}

// 监听渲染
watch(chartData, async val => { if (!val.length) return; await nextTick(); renderChart() })

// 图表
const renderChart = () => {
  if (!chartRef.value) return
  if (!chartInstance) { chartInstance = echarts.init(chartRef.value); window.addEventListener('resize', handleResize) }
  const xData = chartData.value.map(i => i.label)
  const yData = chartData.value.map(i => i.cost)
  const allSame = yData.length > 0 && yData.every(v => v === yData[0])
  const yMin = allSame ? yData[0] - 1 : null
  const yMax = allSame ? yData[0] + 1 : null
  const option = {
    tooltip: { trigger: 'axis', formatter: params => params.map(p => `${p.axisValue}<br/>成本: ${formatMoney(p.data)} 元`).join('') },
    grid: {left: 50, right: 20, top: 40, bottom: 60},
    xAxis: { type: 'category', data: xData, boundaryGap: false, axisLabel: { rotate: xData.length > 6 ? 30 : 0 } },
    yAxis: { type: 'value', name: '成本', min: yMin, max: yMax, axisLabel: { formatter: v => v } },
    series: [{ name: '成本', type: 'line', step: 'end', data: yData, showSymbol: true, smooth: false, areaStyle: {opacity: 0.05} }]
  }
  chartInstance.setOption(option)
  chartInstance.resize()
}

const handleResize = () => { chartInstance && chartInstance.resize() }
const disposeChart = () => { if (chartInstance) { window.removeEventListener('resize', handleResize); chartInstance.dispose(); chartInstance = null } }

// 显示格式
const formatMoney = v => (v == null || v === '' ? '0.00' : Number(v).toFixed(2))

onMounted(() => { initMonthRange(); initDayRange() })
onBeforeUnmount(() => { disposeChart() })
</script>

<style scoped lang="scss">
.CostQuery {
  &-toolbar { padding: 16px 0; border-bottom: 1px solid #eee; display: flex; flex-direction: column; gap: 8px; }
  &-form { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start; }
  &-actions { display: flex; justify-content: flex-end; gap: 8px; }
  &-range { display: flex; align-items: center; gap: 8px; }
  &-range-select { width: 120px; }
  &-range-sep { color: #606266; }
  &-productSelect { display: flex; align-items: center; gap: 12px; min-width: 260px; }
  &-productSelect-info { display: flex; gap: 8px; font-size: 14px; color: #303133; }
  &-productSelect-code { font-weight: 600; }
  &-productSelect-name { max-width: 160px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  &-placeholder { padding: 32px 0; text-align: center; color: #909399; font-size: 14px; }
  &-chartWrapper { padding: 16px 0; position: relative; }
  &-chart { width: 100%; height: 420px; }
  &-chartLoading { position: absolute; inset: 0; background: rgba(255, 255, 255, .75); display: flex; align-items: center; justify-content: center; font-size: 14px; color: #606266; border: 1px solid #ebeef5; }
}
</style>
